/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mrp.productionPlanning.session;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import mrp.productionPlanning.entity.DailyDetailEntity;
import mrp.productionPlanning.entity.MonthlyDetailEntity;
import mrp.productionPlanning.entity.WeeklyDetailEntity;

/**
 *
 * @author Wei Haoyang
 */
@Stateless
@LocalBean
public class DailyDetailSessionBean {

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    @PersistenceContext
    private EntityManager em;
    private DailyDetailEntity dd;
    private SimpleDateFormat formatter = new SimpleDateFormat("dd/mm/yyyy");
    @EJB
    MonthlyDetailSessionBean mdsb = new MonthlyDetailSessionBean();
    @EJB
    WeeklyDetailSessionBean wdsb = new WeeklyDetailSessionBean();

    public DailyDetailEntity getDailyDetailByDate(Date d){
        SimpleDateFormat sdf = new SimpleDateFormat("dd/mm/yyyy");
        String temp = sdf.format(d);
        Calendar cal = new GregorianCalendar();
        cal.setTime(d);
        int correction = cal.get(Calendar.MONTH); 
        try{
            d = sdf.parse(temp);
        }
        catch(ParseException ex){}
        cal.setTime(d);
        cal.set(Calendar.MONTH, correction);
        Timestamp ts = new Timestamp(cal.getTime().getTime());
        ts.setMinutes(1);
//        System.out.println(ts);
        java.sql.Date sd = new java.sql.Date(d.getTime());
        Query query = em.createQuery("SELECT u FROM DailyDetailEntity u where u.ts = :dd");
        query.setParameter("dd", ts);
//        System.out.println("--------------------Check Point--------------------");
//        System.out.println(query.getResultList().size());
        DailyDetailEntity dd = null;
        try {
            dd = (DailyDetailEntity) query.getSingleResult();
        } catch (NoResultException ex) {
            System.out.println("Get Day No result");
            //throw ex;
        }
        //System.out.println(dd.getDate());
        return dd;
    }

    public DailyDetailEntity getDailyDetailById(Long id) {
        return em.find(DailyDetailEntity.class, id);
    }

    public void addDailyDetail(DailyDetailEntity dd) {
        dd.calculateTotalTime();
        dd.calculateCapacity();
        dd.getTs().setTime(dd.getDate().getTime());
        em.persist(dd);
    }

    public void updateDailyDetail(DailyDetailEntity dd) {
        em.merge(dd);
        em.flush();
        System.out.println("***********************Start of UpdateDaily*******************************");
        System.out.println("4 productions: "+dd.getScheduleA() + ";"+ dd.getScheduleB()+";"+dd.getScheduleC()+";"+dd.getScheduleD());
        System.out.println("totalTimeFirst: "+ dd.calculateTotalTime());
        dd.setTotalTime(dd.calculateTotalTime());
        System.out.println("totalTime is : "+dd.getTotalTime());
        dd.calculateCapacity();
        System.out.println("LeftCapacity is :"+dd.getLeftCapacity() +"; " +dd.getLeftOvertime());
        em.merge(dd);
        em.flush();
        System.out.println("*************************End of UpdateDaily*******************************");
        
        if (dd.getMonth() != null && dd.getWeek() != null){
            MonthlyDetailEntity month = dd.getMonth();
            WeeklyDetailEntity week = dd.getWeek();
//            mdsb.updateProduction(month);
//            wdsb.updateProduction(week);
            month.calculateProduction();
            week.calculateProduction();
            mdsb.updateMonthlyDetail(month);
            wdsb.updateWeeklyDetail(week);
        }
//        MonthlyDetailEntity month = new MonthlyDetailEntity();
//        WeeklyDetailEntity week = new WeeklyDetailEntity();
//        Calendar cal = new GregorianCalendar();
//        cal.setTime(dd.getDate());
//        cal.set(Calendar.DAY_OF_MONTH, 1);
//        month = mdsb.getMonthlyDetailByDate(cal.getTime());
//        week = wdsb.getWeeklyDetailByDate(cal.getTime());
//        mdsb.updateProduction(month);
//        wdsb.updateWeeklyDetail(week);
    }

    public void generateAYear(int year) throws ParseException {
        Date d = null;
        Calendar cal = new GregorianCalendar();
        String s = "01/01/" + year;
        try {
            d = formatter.parse(s); 
        } catch (ParseException e) {
            e.printStackTrace();
        }
        cal.setTime(d);
        Date temp = null;
        while ((cal.getTime().getYear()+1900) == year) {
            if (cal.get(Calendar.DAY_OF_WEEK) ==  1 || cal.get(Calendar.DAY_OF_WEEK) == 7) {
                cal.add(Calendar.DATE, 1);
                System.out.println(cal.getTime());
            } else {
                DailyDetailEntity dde = new DailyDetailEntity();
                dde.setDate(cal.getTime());
                System.out.println("--------------Date Check---------------");
                System.out.println(dde.getDate());
                dde.getTs().setTime(dde.getDate().getTime());
                System.out.println("--------------Timestamp Check---------------");
                System.out.println(dde.getTs());
                System.out.println("--------------STRDate Check---------------");
                addDailyDetail(dde);
                cal.add(Calendar.DATE, 1);
            }
        }
//        initiateValue();
        return;
    }

    public void removeDailyDetailByDate(Date d) {
        DailyDetailEntity dd = getDailyDetailByDate(d);
        em.remove(dd);
    }
    
    public void removeDailyDetail(DailyDetailEntity day){
        MonthlyDetailEntity month = day.getMonth();
        WeeklyDetailEntity week = day.getWeek();
        System.out.println(day.getScheduleA() != 0);
        System.out.println(day.getScheduleB() != 0);
        System.out.println(day.getScheduleC() != 0);
        System.out.println(day.getScheduleD() != 0);
        if ((day.getScheduleA() == 0) && (day.getScheduleD() == 0) && (day.getScheduleC() == 0 )&&(day.getScheduleD() == 0)){
            for (int i = 0; i < month.getDays().size(); i++){
                if (month.getDays().get(i).getId().equals(day.getId())){
                    System.out.println("The date to remove for MONTH: "+month.getDays().get(i).getDate().toString());
                    month.getDays().remove(i);
                    mdsb.updateMonthlyDetail(month);
                }
                else System.out.println("This is not the day for month");
            }
            for (int i = 0; i < week.getDays().size(); i++){
                if (week.getDays().get(i).getId().equals(day.getId())){
                    System.out.println("The date to remove for WEEK: "+week.getDays().get(i).getDate().toString());
                    week.getDays().remove(i);
                    wdsb.updateWeeklyDetail(week);
                }
                else System.out.println("This is not the day for week");
            }
            day.setMonth(null);
            day.setWeek(null);
            em.merge(day);
            day = em.find(DailyDetailEntity.class, day.getId());
            em.remove(day);
        }
    }
    
    public List<DailyDetailEntity> getAllDays(){
        Query query  = em.createQuery("SELECT u FROM DailyDetailEntity u");
        List<DailyDetailEntity> dd = new ArrayList<DailyDetailEntity>();
        dd = query.getResultList();
        return dd;
    }

    public DailyDetailEntity getDd() {
        return dd;
    }

    public void setDd(DailyDetailEntity dd) {
        this.dd = dd;
    }

    public List<DailyDetailEntity> getPeriod(Date d1, Date d2) {
        List<DailyDetailEntity> period = new ArrayList<DailyDetailEntity>();
        Calendar cal = new GregorianCalendar();
        cal.setTime(d1);
        DailyDetailEntity schedule;
        while (cal.getTime().before(d2)) {
            schedule = getDailyDetailByDate(cal.getTime());
            if (schedule != null){          //exculde public holidays
                period.add(schedule);
            }
            cal.add(Calendar.DATE, 1);
        }
        period.add(getDailyDetailByDate(d2));
        return period;
    }
    
    public void setMonth(){
        List<DailyDetailEntity> days = new ArrayList<DailyDetailEntity>();
        days = getAllDays();
        MonthlyDetailEntity md = new MonthlyDetailEntity();
        Calendar cal = new GregorianCalendar();
        for (DailyDetailEntity day : days){
            cal.setTime(day.getDate());
            cal.set(Calendar.DAY_OF_MONTH, 1);
            md = mdsb.getMonthlyDetailByDate(cal.getTime());
            day.setMonth(md);
            updateDailyDetail(day);
            System.out.println("-----------Finished " + day.getDate() + "--------------------");
        }
    }
    
    public void setWeek(){
        List<DailyDetailEntity> days = new ArrayList<DailyDetailEntity>();
        days = getAllDays();
        WeeklyDetailEntity wd = new WeeklyDetailEntity();
        Calendar cal = new GregorianCalendar();
        for (DailyDetailEntity day:days){
            cal.setTime(day.getDate());
            cal.set(Calendar.DAY_OF_WEEK, 2);
            wd = wdsb.getWeeklyDetailByDate(cal.getTime());
            day.setWeek(wd);
            updateDailyDetail(day);
        }
    }
    
    public void initiateValue(){
//        List<DailyDetailEntity> days = new ArrayList<DailyDetailEntity>();
//        days = getAllDays();
//        MonthlyDetailEntity md = new MonthlyDetailEntity();
//        double a = 0;
//        double b = 0;
//        double c = 0;
//        double d = 0;
//        int ai = 0;
//        int bi = 0;
//        int ci = 0;
//        int di = 0;
//        Calendar cal = new GregorianCalendar();
//        for (DailyDetailEntity day: days){
//            cal.setTime(day.getDate());
//            cal.set(Calendar.DAY_OF_MONTH, 1);
//            md = mdsb.getMonthlyDetailByDate(cal.getTime());
//            a = md.getScheduleA()/md.getDays().size();
//            ai = (int) Math.ceil(a);
//            b = md.getScheduleB()/md.getDays().size();
//            bi = (int) Math.ceil(b);
//            c = md.getScheduleC()/md.getDays().size();
//            ci = (int) Math.ceil(c);
//            d = md.getScheduleD()/md.getDays().size();
//            di = (int) Math.ceil(d);
//            day.setScheduleA(ai);
//            day.setScheduleB(bi);
//            day.setScheduleC(ci);
//            day.setScheduleD(di);
//            updateDailyDetail(day);
//        }
        List<MonthlyDetailEntity> months = new ArrayList<MonthlyDetailEntity>();
        List<DailyDetailEntity> days = new ArrayList<DailyDetailEntity>();
        months = mdsb.getAllMonths();
        for (MonthlyDetailEntity month:months){
            days = month.getDays();
            int aA = month.getScheduleA()/days.size();
            int aB = month.getScheduleB()/days.size();
            int aC = month.getScheduleC()/days.size();
            int aD = month.getScheduleD()/days.size();
            System.out.println("aA: "+aA);
            System.out.println("aB: "+aB);
            System.out.println("aC: "+aC);
            System.out.println("aD: "+aD);
            int lA = month.getScheduleA() - (aA*days.size());
            int lB = month.getScheduleB() - (aB*days.size());
            int lC = month.getScheduleC() - (aC*days.size());
            int lD = month.getScheduleD() - (aD*days.size());
            System.out.println("lA: "+lA);
            System.out.println("lB: "+lB);
            System.out.println("lC: "+lC);
            System.out.println("lD: "+lD);
            for (DailyDetailEntity day:days){
                if (lA>0){
                    lA-=1;
                    day.setScheduleA(aA+1);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleA :" + day.getScheduleA());
                }
                else {
                    day.setScheduleA(aA);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleA :" + day.getScheduleA());
                }
                if (lB>0){
                    lB-=1;
                    day.setScheduleB(aB+1);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleB :" + day.getScheduleB());
                }
                else {
                    day.setScheduleB(aB);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleB :" + day.getScheduleB());
                }
                if (lC>0){
                    lC-=1;
                    day.setScheduleC(aC+1);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleB :" + day.getScheduleB());
                }
                else {
                    day.setScheduleC(aC);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleB :" + day.getScheduleB());
                }
                if (lD>0){
                    lD-=1;
                    day.setScheduleD(aD+1);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleB :" + day.getScheduleB());
                }
                else {
                    day.setScheduleD(aD);
                    System.out.println("Date: " + day.getDate().toString());
                    System.out.println("scheduleB :" + day.getScheduleB());
                }
                updateDailyDetail(day);
            }
            System.out.println("***************************************************************");
        }
    }
}
